﻿using System;

namespace Simp.CodeModel.CoreFunctions.Sequences
{
	/// <summary>Encapsulates a function selecting one element out of a sequence.</summary>
	public class ElementSelectorFunction : IFunction, IFunctionSerializer
	{
		private static readonly string[] PARAMETER_NAMES = new[] { "source", "index" };

		/// <summary>Name of the function.</summary>
		public const string ElementSelectorFunctionName = "SequenceElement";

		#region IFunction Members
		string IFunction.FunctionName
		{
			get { return ElementSelectorFunctionName; }
		}

		string[] IFunction.ParameterNames
		{
			get { return PARAMETER_NAMES; }
		}

		IFunctionParameterBinding[] IFunction.DefaultParameterValues
		{
			get { return FunctionHelper.EmptyBindings; }
		}

		IFunction IFunction.Simplify(SimplificationMode simplificationMode, params IFunction[] parameters)
		{
			FunctionHelper.ValidateParameters(this, parameters);

			ISequenceAccessor accessor = FunctionHelper.GetAccessor(parameters[0]);
			IntegerFunction index = parameters[1] as IntegerFunction;

			if (accessor == null || index == null)
			{
				return null;
			}
			else
			{
				int count = accessor.Count;
				int indexValue = index.Value;

				if (indexValue >= count || indexValue < -count)
				{
					return null;
				}
				else
				{
					return accessor[indexValue >= 0 ? indexValue : count + indexValue];
				}
			}
		}

		IFunction IFunction.AcceptVisitor(IFunctionVisitor visitor)
		{
			return null;
		}
		#endregion

		#region IFunctionSerializer Members
		void IFunctionSerializer.Serialize(AppendOnlyStringBuilder builder, params IFunction[] parameters)
		{
			FunctionHelper.ValidateParameters(this, parameters);

			IFunction sequence = parameters[0];
			IFunction index = parameters[1];

			FunctionHelper.Serialize(sequence);
			builder.Append("[");
			FunctionHelper.Serialize(index);
			builder.Append("]");
		}
		#endregion
	}
}